/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ //package org.openide.src; package org.openide.src; import org.openide.src.JavaDocTag; /** * Represents a documentation tag, e.g. @since, @author, @version. * Given a tag (e.g. "@since 1.2"), holds tag name (e.g. "@since") * and tag text (e.g. "1.2"). Tags with structure or which require * special processing are handled by special interfaces (JavaDocTag.See, * JavaDocTag.Param, JavaDocTag.Throws and JavaDocTag.SerialField). * The interfaces provide subset of methods defined in Tag interfaces * in the Doclet API. The implementation holds informations about tags in * memory. * * @author Petr Hrebejk * @see JavaDoc#getTags() * */ class JavaDocTagMemoryImpl implements JavaDocTag { String name; String text; JavaDocTagMemoryImpl( String name, String text ) { this.name = name; this.text = text; } public String toString() { return name + " " + text; // NOI18N } // PENDING remove this method void Warning( String t1, String t2 ) { if (System.getProperty("netbeans.debug.exceptions") != null) System.out.println ( "WARNING: " + t1 + t2 ); // NOI18N } /** * Return the name of this tag. */ public String name() { return name; } /** * Return the kind of this tag. */ public String kind() { return name; } /** * Return the text of this tag, that is, portion beyond tag name. */ public String text() { return text; } // TAG private & utility methods ------------------------------------------------------ /** * for use by subclasses which have two part tag text. */ String[] divideAtWhite() { String[] sa = new String[2]; int len = text.length(); // if no white space found sa[0] = text; sa[1] = ""; // NOI18N for (int inx = 0; inx < len; ++inx) { char ch = text.charAt(inx); if (Character.isWhitespace(ch)) { sa[0] = text.substring(0, inx); for (; inx < len; ++inx) { ch = text.charAt(inx); if (!Character.isWhitespace(ch)) { sa[1] = text.substring(inx, len); break; } } break; } } return sa; } // INNER CLASSES ---------------------------------------------------------------------- /** * Represents a see also documentation tag. * */ static class See extends JavaDocTagMemoryImpl implements JavaDocTag.See { private String label = ""; // NOI18N /** where#what */ private String where; private String what; See( String name, String text ) { super( name, text ); parseSeeString(); } /** * Return the label of the see tag. */ public String label() { return label; } /** * get the class name part of @see, For instance, * if the comment is @see String#startsWith(java.lang.String) . * This function returns String. * Returns null if format was not that of java reference. * Return empty string if class name was not specified.. */ public String referencedClassName() { return where; } /** * get the name of the member referenced by the prototype part of @see, * For instance, * if the comment is @see String#startsWith(java.lang.String) . * This function returns "startsWith(java.lang.String)" * Returns null if format was not that of java reference. * Return empty string if member name was not specified.. */ public String referencedMemberName() { return what; } /** * Return the kind of this tag. */ public String kind() { return "@see"; // NOI18N } /** * Return the rawText for this tag */ public String toString() { StringBuffer sb = new StringBuffer( 100 ); sb.append( name ).append( " " ); // NOI18N if ( referencedClassName() != null ) sb.append( referencedClassName() ); sb.append( "#" ); // NOI18N if ( referencedMemberName() != null ) sb.append( referencedMemberName() ); sb.append( " " ); // NOI18N if ( label != null ) sb.append( label ); return sb.toString(); } // SEE TAG private & utility methods -------------------------------------------------- /** * parse @see part of comment. Determine 'where' and 'what' */ private void parseSeeString( ) { int len = text.length(); if (len == 0) { return; } switch (text.charAt(0)) { case '<': if (text.charAt(len-1) != '>') { this.Warning("tag.see.no_close_bracket_on_url", text); // NOI18N } return; case '"': if (len == 1 || text.charAt(len-1) != '"') { this.Warning("tag.see.no_close_quote", text); // NOI18N } else { // text = text.substring(1,len-1); // strip quotes } return; } // check that the text is one word, with possible parentheses // this part of code doesn't allow // @see <a href=.....>asfd</a> // comment it. // the code assumes that there is no initial white space. int parens = 0; int commentstart = 0; int start = 0; for (int i = start; i < len ; i++) { char ch = text.charAt(i); switch (ch) { case '(': parens++; break; case ')': parens--; break; case '[': case ']': case '.': case '#': break; case ',': if (parens <= 0) { this.Warning("tag.see.malformed_see_tag", text); // NOI18N return; } break; case ' ': case '\t': case '\n': if (parens == 0) { //here onwards the comment starts. commentstart = i; i = len; } break; default: if (!Character.isJavaIdentifierPart(ch)) { this.Warning("tag.see.illegal_character", "" + ch + text); // NOI18N return; } break; } } if (parens != 0) { this.Warning("tag.see.malformed_see_tag", text); // NOI18N return; } String seetext = ""; // NOI18N String labeltext = ""; // NOI18N if (commentstart > 0) { seetext = text.substring(start, commentstart); labeltext = text.substring(commentstart + 1); // strip off the white space which can be between seetext and the // actual label. for (int i = 0; i < labeltext.length(); i++) { char ch = labeltext.charAt(i); if (!(ch == ' ' || ch == '\t' || ch == '\n')) { label = labeltext.substring(i); break; } } } else { seetext = text; label = ""; // NOI18N } int sharp = seetext.indexOf('#'); if (sharp >= 0) { // class#member where = seetext.substring(0, sharp); what = seetext.substring(sharp + 1); } else { if (seetext.indexOf('(') >= 0) { this.Warning("tag.see.missing_sharp", text); // NOI18N where = ""; // NOI18N what = seetext; } else { // no member specified, text names class where = seetext; what = null; } } } } /** * Represents an @param documentation tag. * The parses and stores the name and comment parts of the * method/constructor parameter tag. */ static class Param extends JavaDocTagMemoryImpl implements JavaDocTag.Param { private String parameterName; private String parameterComment; Param( String name, String text ) { super( name, text ); String[] sa = this.divideAtWhite(); this.parameterName = sa[0]; this.parameterComment = sa[1]; /* if (!(holder instanceof ExecutableMemberDocImpl)) { Warning("tag.not_on_method", " " this.text ); } */ } /** * Return the parameter name. */ public String parameterName() { return parameterName; } /** * Return the parameter comment. */ public String parameterComment() { return parameterComment; } /** * Return the kind of this tag. */ public String kind() { return "@param"; // NOI18N } /** * Return the rawText for this tag */ public String toString() { return name + " " + parameterName() + " " + parameterComment(); // NOI18N } } /** * Represents a @throws or @exception documentation tag. * Parses and holds the exception name and exception comment. * Note: @exception is a backwards compatible synonymy for @throws. */ static class Throws extends JavaDocTagMemoryImpl implements JavaDocTag.Throws { private String exceptionName; private String exceptionComment; Throws( String name, String text ) { super( name, text ); /* if (runtimeException == null) { runtimeException = ClassDocImpl.lookup("java.lang.RuntimeException"); } */ String[] sa = this.divideAtWhite(); this.exceptionName = sa[0]; this.exceptionComment = sa[1]; /* if (!(holder instanceof ExecutableMemberDocImpl)) { Res.warning("tag.not_on_method", holder.toString(), this.text); exceptionClass = null; } else { ExecutableMemberDocImpl emd = (ExecutableMemberDocImpl)holder; ClassDoc con = emd.containingClass(); exceptionClass = con.findClass(exceptionName); if (exceptionClass == null) { // may just not be in this run // Res.warning("tag.throws.exception_not_found", // emd.qualifiedName(), kind(), exceptionName); } else { if (!isOK(exceptionClass, emd.thrownExceptions())) { Res.warning("tag.throws.does_not_declare", emd.qualifiedName(), exceptionClass.qualifiedName()); } } } */ } /** * Return the exception name. */ public String exceptionName() { return exceptionName; } /** * Return the exception comment. */ public String exceptionComment() { return exceptionComment; } /** * Return the kind of this tag. Always "@throws" for instances * of ThrowsTagImpl. */ public String kind() { return "@throws"; // NOI18N } /** * Return the rawText for this tag */ public String toString() { return name + " " + exceptionName() + " " + exceptionComment(); // NOI18N } } /** * Documents a Serializable field defined by an ObjectStreamField. * <pre> * The class parses and stores the three serialField tag parameters: * * - field name * - field type name * (fully-qualified or visible from the current import context) * - description of the valid values for the field * </pre> * This tag is only allowed in the javadoc for the special member * * @see java.io.ObjectStreamField */ static class SerialField extends JavaDocTagMemoryImpl implements JavaDocTag.SerialField { private String fieldName; private String fieldType; private String description; SerialField( String name, String text ) { super( name, text ); parseSerialFieldString( text ); } /** * Return the serialziable field name. */ public String fieldName() { return fieldName; } /** * Return the field type string. */ public String fieldType() { return fieldType; } /** * Return the field comment. If there is no serialField comment, return * javadoc comment of corresponding FieldDoc. */ public String description() { return description; } /** * Return the kind of this tag. */ public String kind() { return "@serialField"; // NOI18N } /** * Return the rawText for this tag */ public String toString() { return name + " " + fieldName() + " " + fieldType() + " " + description(); // NOI18N } /* * The serialField tag is composed of three entities. * * serialField serializableFieldName serisliableFieldType * description of field. * * The fieldName and fieldType must be legal Java Identifiers. */ private void parseSerialFieldString( String text) { int len = text.length(); // if no white space found // Skip white space. int inx = 0; for (; inx < len && Character.isWhitespace(text.charAt(inx)); inx++) ; if ( inx == len ) { fieldName = ""; // NOI18N fieldType = ""; // NOI18N description = ""; // NOI18N return; } // Find first word. int first = inx; int last = inx; if (! Character.isJavaIdentifierStart(text.charAt(inx))) { this.Warning("tag.serialField.illegal_character", ""+ text.charAt(inx) + " " + text); // NOI18N return; } for (; inx < len && Character.isJavaIdentifierPart(text.charAt(inx)); inx++); if (inx < len && ! Character.isWhitespace(text.charAt(inx))) { this.Warning("tag.serialField.illegal_character", ""+ text.charAt(inx) + " " + text); // NOI18N return; } last = inx; fieldName = text.substring(first, last); // Skip white space. for (; inx < len && Character.isWhitespace(text.charAt(inx)); inx++) ; // Find second word. first = inx; last = inx; for (; inx < len && ! Character.isWhitespace(text.charAt(inx)); inx++); if (inx < len && ! Character.isWhitespace(text.charAt(inx))) { this.Warning("tag.serialField.illegal_character", ""+ text.charAt(inx) + " " + text); // NOI18N return; } last = inx; fieldType = text.substring(first, last); // Skip leading white space. Rest of string is description for serialField. for (; inx < len && Character.isWhitespace(text.charAt(inx)); inx++) ; description = text.substring(inx); } } } /* * Log * 9 Gandalf 1.8 1/16/00 Ian Formanek Removed semicolons after * methods body to prevent fastjavac from complaining * 8 Gandalf 1.7 1/12/00 Petr Hamernik i18n using perl script * (//NOI18N comments added) * 7 Gandalf 1.6 1/3/00 Petr Hrebejk Bug fix 4740, 4975 * 6 Gandalf 1.5 12/8/99 Petr Hamernik compilable by Javac V8 * (jdk1.3) * 5 Gandalf 1.4 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 4 Gandalf 1.3 10/10/99 Petr Hamernik console debug messages * removed. * 3 Gandalf 1.2 6/8/99 Ian Formanek ---- Package Change To * org.openide ---- * 2 Gandalf 1.1 6/7/99 Petr Hrebejk Implementations made * package privet * 1 Gandalf 1.0 5/26/99 Petr Hrebejk * $ */